The break loop is a read-eval-print loop similar to the top-level loop. In addition to ordinary Lisp forms, the break loop accepts various commands with which the user can inspect and modify the state of the program execution. Each break loop command is identified with a keyword (i.e., a symbol in the keyword package). A break loop command is executed when the user inputs a list whose first element is the keyword that identifies the command. The rest of the list is the arguments to the command. They are evaluated before being passed to the command. If the command needs no arguments, then the user may input only the keyword. It is an error if the given keyword does not identify any command. Any other input to the break loop is regarded as an ordinary Lisp form; the form will be evaluated and the resulting values will be printed on the terminal.
There can be several instances of the break loop at the same time, and each such instance is identified by a level number. When the break loop is entered during execution in the top-level loop, the break loop instance is given the level number 1 . The break loop instance that is entered from the level n break loop is given the level number n + 1 . The prompt of the level n break loop is n + 1 consecutive >'s, occasionally prefixed with the name of the current package.
The break loop keeps track of the invocation sequence of functions (including special forms and macro expansion functions), which led up to the break loop from the previous break loop (or from the top-level loop, if the current break loop is level 1 ). The invocation sequence is maintained in a pushdown stack of events. An event consists of an event function and an event environment. An event function is:
An event is pushed on the event stack when execution of its event function begins, and is poped away at the completion of the execution. An event environment is the `environment' of the event function at the time the next event is pushed. Actually, an event environment is a pointer to the main stack of KCL. For each interpreted event function (i.e., event function in classes 1, 2, and 3), the pointer points to the first entry of the three contiguous main stack entries that hold the lexical environment of the event function. For each compiled event function (i.e., event function in classes 4 and 5), the pointer is set to the first entry of the main stack area that is used locally by the compiled code. In most cases, the first argument to the compiled function is saved in the first entry, the second argument in the second entry, and so on. The local variables of the function are allocated in the entries following the arguments. However, this is not always the case. Refer to Section 7.3 for variable allocations in compiled functions.
By break level commands, the user can choose one of the events as the current event. If the current event function is an interpreted event function, then the break loop evaluates Lisp forms in the lexical environment retrieved from the event environment. In particular, local variables may be referenced by the variable names, local functions and local macros may be invoked as usual, established blocks may be exited from, and tags may be used as the destination of go. If the current function is a compiled function, Lisp forms are evaluated in the null environment.
Within the break loop, each event is represented by the event symbol. The :backtrace command, for example, lists events in terms of their event symbols. If the event function is a named function (global or local) or a macro expansion function, then the function or macro name is used as the event symbol. If the event function is a special form, then the name of the special form is used. If the event function is a lambda-expression (or a closure), then the symbol lambda (or lambda-closure ) is used.
To suppress unnecessary information, the user can hide (or make invisible) some of the events. Invisible events do not appear in the backtrace, for example. Initially, only those events are invisible whose event symbols belong to the system internal package system. When the break loop is entered, the last visible event becomes the current event.
The break loop commands are described below. Some of the commands allow abbreviation in the keywords that identify them. For example, the user may abbreviate :current as :c. The break loop commands return no values at all.
:current[Break Loop Command]
:c[Abbreviated Break Loop Command]
:previous &optional n[Break Loop Command]
:p &optional n[Abbreviated Break Loop Command]
:next &optional n[Break Loop Command]
:n &optional n[Abbreviated Break Loop Command]
:backtrace[Break Loop Command]
:b[Abbreviated Break Loop Command]
:help[Break Loop Command]
:h[Abbreviated Break Loop Command]
:quit &optional n[Break Loop Command]
:q &optional n[Abbreviated Break Loop Command]
:resume[Break Loop Command]
:r[Abbreviated Break Loop Command]
:variables[Break Loop Command]
:v[Abbreviated Break Loop Command]
:functions[Break Loop Command]
:blocks[Break Loop Command]
:tags[Break Loop Command]
:local &optional n[Break Loop Command]
:l &optional n[Abbreviated Break Loop Command]
:hide symbol[Break Loop Command]
:hide-package package[Break Loop
Command]
:unhide symbol[Break Loop Command]
:unhide-package package[Break Loop
Command]
Example:
>(defun fact (x) (if (= x 0) one (* x (fact (1- x))))) fact ;;; Wrong definition for fact , the factorial. >(fact 6) ;;; Tries to calculate factorial 6. Error: The variable ONE is unbound. Error signalled by IF. Broken at IF: ;;; Enters the break-loop. >>:h ;;; Help. :c(urrent) Shows the current function. :p(revious) To the previous function. :n(ext) To the next function. :b(acktrace) Prints backtrace. :h(elp) Help. :q(uit) Returns to top-level. :r(esume) Returns to the caller of break-level. :l(ocal) Shows the n-th local value on the stack. :v(ariables) Shows local variables. :functions Shows local functions. :blocks Shows block names. :tags Shows tags. :(un)hide(-package) (Un)hide a function (or a package). >>:b ;;; Backtrace. Backtrace: eval > fact > if > fact > if > fact > if > fact > if > fact > if > fact > if > fact > IF >>:p ;;; Moves to the previous event. Broken at FACT. >>:b ;;; Now inside of fact but outside of if . Backtrace: eval > fact > if > fact > if > fact > if > fact > if > fact > if > fact > if > FACT > if >>:v ;;; Shows local variables. Local variables: x. >>x ;;; The value of x is 0 . 0 >>:blocks ;;; Shows blocks. Block names: fact. >>(return-from fact 1) ;;; Returns from the fact block with value 1 . 720 ;;; Now the correct answer. > ;;; Top-level.